// 一个最小可运行的 UDP 回显服务器。
// - 监听 127.0.0.1:5678
// - 接收来自任意客户端的报文
// - 将报文原样发送回来源地址
package main

import (
	"log"
	"net"
)

func main() {
	// 1. 解析 UDP 地址。与 TCP 不同，需要显式指定协议为 "udp"。
	//    服务端端口号固定为 5678，客户端会在运行时随机选择端口。
	addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5678")
	if err != nil {
		log.Fatalf("resolve addr error: %v", err)
	}

	// 2. ListenUDP 直接返回 *net.UDPConn。
	//    与 TCP 不同：没有 Accept 阶段、不会阻塞等待连接。
	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		log.Fatalf("listen udp error: %v", err)
	}
	defer conn.Close()
	log.Println("UDP 服务器已启动（非阻塞），等待客户端数据 ...")

	// 256 字节的读缓冲，可按需调整。
	buf := make([]byte, 256)

	for {
		// 3. ReadFromUDP 会返回：
		//    - n：读取到的实际字节数
		//    - remoteAddr：客户端地址（包含 IP 与端口）
		//    - err：错误信息
		n, remoteAddr, err := conn.ReadFromUDP(buf)
		if err != nil {
			log.Printf("read error: %v", err)
			continue
		}

		log.Printf("收到 %d 字节，来自 %s：%q",
			n, remoteAddr.String(), string(buf[:n]))

		// 4. UDP 无连接。回复时必须显式指定目标地址。
		if _, err := conn.WriteToUDP(buf[:n], remoteAddr); err != nil {
			log.Printf("write error: %v", err)
		}
	}
}
